#include <cstring>

#include "CMP.h"

CMP::CMP(uint32_t threads, uint32_t pageSize, uint32_t lineSize, uint32_t L0Size)
    : _threads(threads), _pageSize(pageSize), _lineSize(lineSize), _L0Size(L0Size),_L0Flush(0)
{
    for (int i=0;i<_threads;i++) {
        _tlb[i] = new TLB(TLB_SIZE*_pageSize,_pageSize,i);
        if (_L0Size>0)
            _L0Cache[i] =  new CacheWriteBack<address_t> (_L0Size,4,lineSize,false,1);
    }

    /* L0 cache stats */
    if  (_L0Size>0) {
        _L0CacheHits = new uint32_t [threads];
        _L0CacheMisses = new uint32_t [threads];
    }
    _mainMemoryAccesses = new uint32_t [threads];
}

CMP::~CMP()
{
    // TODO: if L0Cache > 0
    for (int i=0;i<_threads;i++) {
        delete _tlb[i];
        if (_L0Size>0) {
            delete _L0Cache[i];
        }
    }
    if (_L0Size>0) {
        delete [] _L0CacheHits;
        delete [] _L0CacheMisses;
    }
    delete [] _mainMemoryAccesses;
}

void
CMP::reset()
{
    if  (_L0Size>0) {
        memset(_L0CacheHits,0,sizeof(uint32_t)*_threads);
        memset(_L0CacheMisses,0,sizeof(uint32_t)*_threads);
    }
    memset(_mainMemoryAccesses,0,sizeof(uint32_t)*_threads);
    _L0Flush=0;
}

void
CMP::flushL0(uint32_t thread)
{
    if (_L0Size>0) {
        _L0Cache[thread]->flush();
        _L0Flush++;
    }
}
